package com.yc.sole.framework.utils;

import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.text.CharSequenceUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.lionsoul.ip2region.xdb.Searcher;

import java.io.File;
import java.io.InputStream;
import java.util.List;

/**
 * @author yizuomin
 * @date 2023/5/16 22:36
 **/
@Slf4j
public class IpUtil {

    private static Searcher searcher = null;

    static {
        try {
            String dbPath = IpUtil.class.getResource("/ip2region.xdb").getPath();
            File file = new File(dbPath);
            if (!file.exists()) {
                String tmpDir = System.getProperties().getProperty("java.io.tmpdir");
                dbPath = (tmpDir.endsWith(File.separator) ? tmpDir : tmpDir + File.separator) + "ip2region.xdb";
                file = new File(dbPath);
                String classPath = "classpath:ip2region.xdb";
                InputStream resourceAsStream = ResourceUtil.getStreamSafe(classPath);
                if (resourceAsStream != null) {
                    FileUtils.copyInputStreamToFile(resourceAsStream, file);
                }
            }
            // 1、从 dbPath 加载整个 xdb 到内存。
            byte[] cBuff = null;
            try {
                cBuff = Searcher.loadContentFromFile(dbPath);
            } catch (Exception e) {
                log.error("failed to load content from `%s`: %s\n", dbPath, e);
            }

            // 2、使用上述的 cBuff 创建一个完全基于内存的查询对象。
            try {
                searcher = Searcher.newWithBuffer(cBuff);
            } catch (Exception e) {
                log.error("failed to create content cached searcher: %s\n", e);
            }

            log.info("bean [{}]", searcher);
        } catch (Exception e) {
            log.error("ip解析器初始化失败", e);
        }
    }

    /**
     * 解析IP
     *
     * @param ip ip
     * @return 地区
     */
    public static IPInfo getRegion(String ip) {
        try {
            //db
            if (searcher == null || CharSequenceUtil.isEmpty(ip)) {
                log.error("Searcher is null");
                return new IPInfo();
            }
            long startTime = System.currentTimeMillis();
            String result = searcher.search(ip);
            long endTime = System.currentTimeMillis();
            log.debug("解析ip耗时：【{}】 毫秒，结果：【{}】", endTime - startTime, result);
            if (CharSequenceUtil.isNotBlank(result)) {
                List<String> stringList = CharSequenceUtil.split(result, "|");
                IPInfo ipInfo = new IPInfo();
                ipInfo.setIsp(stringList.get(stringList.size() - 1));
                ipInfo.setAddress(CharSequenceUtil.join("|", stringList.get(0), stringList.get(2), stringList.get(3)));
                return ipInfo;
            }
            return new IPInfo();

        } catch (Exception e) {
            log.error("根据ip查询地区失败:", e);
        }
        return new IPInfo();
    }

    public static String getIpAddress(HttpServletRequest request) {
        String ipAddress = request.getHeader("x-forwarded-for");
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
        }
        int index = ipAddress.indexOf(",");
        if (index != -1) {
            ipAddress = ipAddress.substring(0, index);
        }
        return ipAddress;
    }

    @Data
    public static class IPInfo {
        /**
         * 地址
         */
        private String address;
        /**
         * isp
         */
        private String isp;
    }
}
